#pragma once
#include "socket.hpp"
#include "channel.hpp"
namespace Muduo
{
    class Accepter
    {
    public:
        using AccpetCallback = std::function<void(int)>;

        //不能将启动读事件监控,放到构造函数中,必须在设置回调函数后,再去启动
        //否则有可能造成启动之后,立即有事件,处理的时候,回调函数还没设置,新链接得不到处理,造成资源泄露
        Accepter(EventLoop * loop,int port):_socket(CreateServer(port)),_loop(loop),
        _channel(loop,_socket.Fd())
        {
            _channel.SetReadCallback(std::bind(&Accepter::HandleRead,this));
        }

        void SetAcceptCallback(const AccpetCallback & cb)
        {
            _accpet_callback = cb;
        }

        void Listen()
        {
            _channel.EnableRead();
        }

    private:
        //监听套接字的读事件回调处理函数---获取新链接,调用_accept_callback函数进行新链接处理
        void HandleRead()
        {
            int newfd = _socket.Accept();
            if(newfd<0)
            {
                return;
            }
            if(_accpet_callback) _accpet_callback(newfd);
        }

        int CreateServer(int port)
        {
            bool ret = _socket.CreateServer(port);
            assert(ret == true);
            return _socket.Fd();
        }

    private:
        Socket _socket;//用于创建监听套接字
        EventLoop * _loop;//用于对监听套接字进行事件监控->可读事件
        Channel _channel;//用于对监听套接字进行事件管理
        AccpetCallback _accpet_callback;//连接到来的回调函数处理
    };
}